package org.nViron.nvParams;

//~--- non-JDK imports --------------------------------------------------------

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.nViron.nvData.nvDataEntity;
import org.nViron.nvParams.nvContextParamMgr.CONTEXTPARAM;
import org.nViron.nvParams.nvVizParamMgr.VIZPARAM;

/**
 * Defines a rule how a visualization parameter is calculated out of context parameters
 * @author Roland Haring <p>
 * <script type="text/javascript" src="http://www.ohloh.net/p/376434/widgets/project_basic_stats.js"></script>
 */
public class nvParamBinding {
    private List     paramTerms = new ArrayList();
    private float    offset;
    private VIZPARAM param;
    private float    weight;

    public nvParamBinding(VIZPARAM param) {
        this.param = param;
    }

    public int addTerm(CONTEXTPARAM param, float weight, float decay, boolean invert) {
        if (weight == 0.0f) {
            return -1;
        }

        paramTerms.add(new nvParamTerm(param, weight, decay, invert));
        this.weight += weight;

        return paramTerms.size() - 1;
    }

    public VIZPARAM getKind() {
        return param;
    }

    public float getOffset() {
        return offset;
    }

    public nvParamTerm getTerm(int i) {
        return (nvParamTerm) paramTerms.get(i);
    }

    float getValueFor(nvDataEntity entity) {
        float ret = 0.0f;

        for (Iterator it = paramTerms.iterator(); it.hasNext(); ) {
            nvParamTerm term = (nvParamTerm) it.next();

            ret += (term.isInverted()
                    ? 1.0f - entity.getContextValue(term.getParam())
                    : entity.getContextValue(term.getParam())) * term.getWeight();

            // TODO decay is missing
        }

        ret *= weight;
        ret += offset;

        if (ret > 1.0f) {
            ret = 1.0f;
        }

        return ret;
    }

    public float getWeight() {
        return weight;
    }

    public void removeTerm(int i) {
        paramTerms.remove(i);
    }

    public void resetRule() {
        paramTerms.clear();
        weight = 0.0f;
        offset = 0.0f;
    }

    public void setOffset(float offset) {
        this.offset = offset;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }

    public int size() {
        return paramTerms.size();
    }

    public boolean usesContextParam(CONTEXTPARAM contextParam) {
        for (Iterator it = paramTerms.iterator(); it.hasNext(); ) {
            nvParamTerm term = (nvParamTerm) it.next();

            if (term.getParam() == contextParam) {
                return true;
            }
        }

        return false;
    }
}



